package com.yash.rms.util;


import java.io.PrintWriter;
import java.io.StringWriter;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * Defines the logger aspect for the web self service app. Contains the point
 * cut and advice definitions for all layers(app/domain)
 * 
 * 
 */
@Component
@Aspect
public class LoggerAspect {

    // app/service layer loggers
	private static final Logger APP_EXCEPTION_LOG = LoggerFactory.getLogger("appExceptionLog");
    private static final Logger APP_LOG = LoggerFactory.getLogger("appLog");
   
    public static void error(String msg , Throwable error){
    	APP_EXCEPTION_LOG.error(msg, error);
    }
    

    /**
     * Below are the advice methods for controller/app layer methods
     * */

    @Before("execution(public * com.yash.rms.controller.*.*(..))")
    public void beforeAppMethod(final JoinPoint joinPoint) {
	APP_LOG.info("App Layer Before Method " + joinPoint.getSignature().toShortString());
	
    }

    @After("execution(public * com.yash.rms.controller.*.*(..))")
    public void afterAppMethod(final JoinPoint joinPoint) {
	APP_LOG.info("App layer After Method " + joinPoint.getSignature().toShortString());
    }

    /**
     * Below are the adivce methods for service layer methods
     */

    @Before("(execution(public * com.yash.rms.domain.*.*(..)) && @annotation(org.springframework.transaction.annotation.Transactional)) || execution(public * com.yash.rms.domain.*.find*(..))")
    public void beforeServiceMethod(final JoinPoint joinPoint) {
    	APP_LOG.info("Service Layer Before Method " + joinPoint.getSignature().toShortString());
    }

    @After("(execution(public * com.yash.rms.domain.*.*(..)) && @annotation(org.springframework.transaction.annotation.Transactional)) || execution(public * com.yash.rms.domain.*.find*(..))")
    public void afterServiceMethod(final JoinPoint joinPoint) {
    	APP_LOG.info("Service layer After Method " + joinPoint.getSignature().toShortString());
    }
        


    /**
     * Advice needs to be executed whenever any method defined in controller
     * throws the exception. This is just for logging the error message in log
     * file.
     * 
     * @param joinPoint
     *            joint point object
     * @param ex
     *            actual excetion object received from target method.
     */

    @AfterThrowing(pointcut = "execution(public * com.yash.rms.controller.*.*(..))", throwing = "exception")
    public void afterServiceException(final JoinPoint joinPoint, final Exception exception) {
		final StringWriter stringWriter = new StringWriter();
		final PrintWriter printWriter = new PrintWriter(stringWriter);
		exception.printStackTrace(printWriter);
		APP_EXCEPTION_LOG.error(stringWriter.toString());
    }
}
